<?php

/**
 * Hammer and Nails Software
 * Copyright (c) 2006-2007 Hammer and Nails Software. (http://www.hansoft.org)
 *
 * LICENSE
 *
 * This source file is subject to the GNU General Public License v3 license 
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.hansoft.org/licenses/gpl-3.0.txt or through the GNU website:
 * http://www.gnu.org/licenses/gpl-3.0.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@hansoft.org so we can send you a copy immediately.
 *
 * @copyright  (c) 2006-2007 Hammer and Nails Software. (http://www.hansoft.org)
 * @license    http://www.hansoft.org/licenses/gpl-3.0.txt
 * @version    $Id: App.php 7 2008-02-17 17:06:58Z philbsd $
 */

class Hansoft_App
{
    protected static $_instance = null;

    public $dirApplication;
    public $dirLibrary;

    public $config;

    public static function getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
            self::$_instance->_initialize();
        }

        return self::$_instance;
    }

    public function run()
    {
        $frontController = Zend_Controller_Front::getInstance();

		/*
		 * Fetch all modules in the database
		*/
		$dirController = array();
		$modules = array();
		$moduleTable = new Hansoft_Model_Modules();
		$moduleRowSet = $moduleTable->fetchAll();
		while ($moduleRow = $moduleRowSet->current()) {
			$module = $moduleRow->toArray();
			$modules[$module['id']] = $module['name'];
			$dirController[$module['name']] = $module['name'] . DS . 'controllers';
			$moduleRowSet->next();
		}

        $frontController->throwExceptions(true)
						->setControllerDirectory($dirController)
						->addModuleDirectory($this->dirApplication . DS . 'modules')
						->registerPlugin(new Hansoft_Controller_Plugin_Dispatch_Check())
						->registerPlugin(new Hansoft_Controller_Plugin_Auth())
						->registerPlugin(new Hansoft_Controller_Plugin_View_Layout())
						->returnResponse(true);

		$acl = Zend_Registry::get('acl');

		/*
		 * Fetch all roles in the database
		*/
        $superUsers = array();
        $roleParents = array();
        $roles = array();
        $roleTable = new Hansoft_Model_Roles();
        $roleRowSet = $roleTable->fetchAll();
        while ($roleRow = $roleRowSet->current()) {
            if ($roleRow->parent_id) {
                $roles[$roleRow->id] = $roleRow;
            } else {
                $roleParents[$roleRow->id] = $roleRow;
            }

            if ($roleRow->super_user) {
                $superUsers[] = $roleRow;
            }
            $roleRowSet->next();
        }

		/*
		 * Add all parent roles to ACL
		*/
        foreach ($roleParents as $roleParent) {
            $acl->addRole(new Zend_Acl_Role($roleParent->name));
        }

		/*
		 * Add roles having parents to ACL (inherit privileges from parent)
		*/
        foreach ($roles as $role) {
            $acl->addRole(new Zend_Acl_Role($role->name), $roleParents[$role->parent_id]->name);
        }

		/*
		 * Fetch all data in module_resource_privileges table
		*/
		$moduleResourcePrivilegeTable = new Hansoft_Model_Module_Resource_Privileges();
		$moduleResourcePrivilegeRowSet = $moduleResourcePrivilegeTable->fetchAll();
		$accessControlLists = array();
		while ($moduleResourcePrivilegeRow = $moduleResourcePrivilegeRowSet->current()) {
			/* Get parent table for module_resource_id */
			if (!isset($moduleResourceRowTmp[$moduleResourcePrivilegeRow->module_resource_id])) {
				$moduleResourceRowTmp[$moduleResourcePrivilegeRow->module_resource_id] = 
							$moduleResourcePrivilegeRow->findParentRow('Hansoft_Model_Module_Resources');
			}
			$moduleResourceRow = $moduleResourceRowTmp[$moduleResourcePrivilegeRow->module_resource_id];
			/* Get parent table for modules in module_resources table */
			if (!isset($moduleRowTmp[$moduleResourceRow->module_id])) {
				$moduleRowTmp[$moduleResourceRow->module_id] = $moduleResourceRow->findParentRow('Hansoft_Model_Modules');
			}
			$moduleRow = $moduleRowTmp[$moduleResourceRow->module_id];
			/* Get parent table for resources in module_resources table */
			if (!isset($resourceRowTmp[$moduleResourceRow->resource_id])) {
				$resourceRowTmp[$moduleResourceRow->resource_id] = $moduleResourceRow->findParentRow('Hansoft_Model_Resources');
			}
			$resourceRow = $resourceRowTmp[$moduleResourceRow->resource_id];
			/* Get parent table for privilege_id  */
			if (!isset($privilegeRowTmp[$moduleResourcePrivilegeRow->privilege_id])) {
				$privilegeRowTmp[$moduleResourcePrivilegeRow->privilege_id] = $moduleResourcePrivilegeRow->findParentRow('Hansoft_Model_Privileges');
			}
			$privilegeRow = $privilegeRowTmp[$moduleResourcePrivilegeRow->privilege_id];

			$resourceId = "{$moduleRow->id}.{$resourceRow->id}";
			$resourceName = "{$moduleRow->name}.{$resourceRow->name}";			
			if (!$acl->has($resourceName)) {
				$acl->add(new Zend_Acl_Resource($resourceName));
			}

			/* Get all ACL's by module_resource_privilege_id  */
			$aclTable = new Hansoft_Model_Acl();
			$aclRowSet = $aclTable->fetchAll("module_resource_privilege_id = {$moduleResourcePrivilegeRow->id}");

			while ($aclRow = $aclRowSet->current()) {
				if (!isset($accessControlLists[$aclRow->role_id]['name'])) {
					$roleRow = $aclRow->findParentRow('Hansoft_Model_Roles');
					$accessControlLists[$roleRow->id]['name'] = $roleRow->name;					
				}

				if (!isset($accessControlLists[$aclRow->role_id]['resources'][$resourceId]['name'])) {
					$accessControlLists[$aclRow->role_id]['resources'][$resourceId]['name'] = $resourceName;
				}
				$accessControlLists[$aclRow->role_id]['resources'][$resourceId]['privileges'][] = $privilegeRow->name;

				$aclRowSet->next();
			}

			$moduleResourcePrivilegeRowSet->next();
		}

		foreach ($accessControlLists as $key=>$val) {
			foreach ($val['resources'] as $resource) {
				$acl->allow($val['name'], $resource['name'], $resource['privileges']);
			}
		}

        foreach ($superUsers as $superUser) {			
            $acl->allow($superUser->name);
        }

        try {
            $response = $frontController->dispatch();
            $response->sendResponse();
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    protected function _initialize()
    {
        error_reporting(E_ALL | E_STRICT);

        $this->dirApplication = dirname(dirname(dirname(__FILE__)));

        $this->dirLibrary = $this->dirApplication . DS . 'lib';

        set_include_path($this->dirLibrary . PS
                       . $this->dirApplication . DS . 'models' . PS
                       . get_include_path());

        require_once 'Zend/Loader.php';
        Zend_Loader::registerAutoload();

        $this->config = new Zend_Config_Xml(
								$this->dirApplication . DS . 'etc' . DS . 
								'config.xml', 'default');
		Zend_Registry::set('config', $this->config);
		Zend_Registry::set('db', Zend_Db::factory($this->config->database));
		Zend_Registry::set('acl', new Zend_Acl());
    }
}
